package com.corpgovernment.organization.service;

import cn.hutool.core.util.IdcardUtil;
import com.corpgovernment.api.organization.bo.SyncOrgEmployeeReq;
import com.corpgovernment.api.organization.bo.SyncOrgEmployeeRsp;
import com.corpgovernment.api.organization.utils.RegularUtils;
import com.corpgovernment.common.enums.CardEnum;
import com.corpgovernment.job.dao.entity.db.JobDo;
import com.corpgovernment.job.dao.mapper.JobMapper;
import com.corpgovernment.job.service.JobService;
import com.corpgovernment.job.service.bo.CheckJobResultBo;
import com.corpgovernment.job.service.bo.JobBo;
import com.corpgovernment.organization.Bo.SyncEmployeeInfoMQBo;
import com.corpgovernment.organization.dataloader.db.MbOrgEmployeeLoader;
import com.corpgovernment.organization.dto.SyncOrgInfoDto;
import com.corpgovernment.organization.entity.db.MbOrgEmployeeInfo;
import com.corpgovernment.organization.entity.db.MbOrgInfo;
import com.corpgovernment.organization.entity.db.MbPostInfo;
import com.corpgovernment.organization.entity.db.MbUserOrgRelation;
import com.corpgovernment.organization.enumm.CardCodeEnum;
import com.corpgovernment.organization.mq.SyncEmployeeInfoMQProducer;
import com.corpgovernment.organization.util.CardTypeSwitchUtil;
import com.corpgovernment.organization.util.IdCardUtil;
import com.ctrip.corp.obt.generic.utils.CollectionUtils;
import com.ctrip.corp.obt.generic.utils.JsonUtils;
import com.ctrip.corp.obt.generic.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Service
@Slf4j
public class SyncOrgEmployeeService {

    @Autowired
    private MbOrgEmployeeLoader mbOrgEmployeeLoader;
    @Autowired
    private IOrganizationEmployeeService organizationEmployeeService;
    @Autowired
    private IUserOrgRelationService userOrgRelationService;
    @Autowired
    private IOrganizationInfoService organizationInfoService;
    @Autowired
    private SyncEmployeeInfoMQProducer syncEmployeeInfoMQProducer;
    @Autowired
    private PositionInfoService positionInfoService;
    @Resource
    private JobMapper jobMapper;
    @Autowired
    private JobService jobService;


    private final static String OpenApi_Action_Status_1 = "1";
    private final static String OpenApi_Action_Status_2 = "2";
    private final static String OpenApi_Action_Status_3 = "3";
    private final static String OpenApi_Action_Status_4 = "4";

    public SyncOrgEmployeeRsp process(SyncOrgEmployeeReq request){
        log.info("SyncOrgEmployee:{}", JsonUtils.toJsonString(request));
        try{
            List<SyncOrgEmployeeReq.Employee> employeeList = request.getEmployeeList();
            if (CollectionUtils.isEmpty(employeeList)){
                return SyncOrgEmployeeRsp.success(Collections.emptyList());
            }
            //导入数据中所有得UID
            List<String> uidList = new ArrayList<>();
            for(SyncOrgEmployeeReq.Employee employee:employeeList){
                if(Objects.nonNull(employee.getBasicInfo()) && StringUtils.isNotBlank(employee.getBasicInfo().getUid())){
                    // uid去掉空格
                    String uid = employee.getBasicInfo().getUid().trim();
                    employee.getBasicInfo().setUid(uid);
                    uidList.add(uid);
                }
                // 将部分证件号码由小写转为大写
                if (CollectionUtils.isNotEmpty(employee.getCardTypeList())){
                    employee.getCardTypeList().forEach(k ->{
                        if (CardEnum.needUpperCaseCard(k.getCardType())){
                            k.setCardNo(k.getCardNo().toUpperCase());
                        }
                    });
                    // 根据身份证号确定生日和性别
                    SyncOrgEmployeeReq.CardType card = employee.getCardTypeList().stream().filter(k -> CardCodeEnum.ID_CARD.getCode().equals(k.getCardType())).findFirst().orElse(null);
                    if (Objects.nonNull(card)) {
                        employee.getBasicInfo().setBirthday(IdCardUtil.getBirth(card.getCardNo()));
                        employee.getBasicInfo().setGender(IdCardUtil.getEnGender(card.getCardNo()));
                    }
                }
            }

            List<MbUserOrgRelation> userOrgRelationList = userOrgRelationService.findByUids(uidList);
            Map<String, MbUserOrgRelation> uidOrgMap = Optional.ofNullable(userOrgRelationList).orElse(Collections.emptyList())
                    .stream().collect(
                            Collectors.toMap(MbUserOrgRelation::getUid, Function.identity(), (k1, k2) -> k1)
                    );

            //导入数据中所有得电话号码
            List<String> mobilePhoneList = employeeList.stream()
                    .filter(item -> Objects.nonNull(item.getBasicInfo()) && StringUtils.isNotBlank(item.getBasicInfo().getMobilePhone()))
                    .map(SyncOrgEmployeeReq.Employee::getBasicInfo)
                    .map(SyncOrgEmployeeReq.BasicInfo::getMobilePhone)
                    .collect(Collectors.toList());
            List<MbOrgEmployeeInfo> mbOrgEmployeeInfos = mbOrgEmployeeLoader.selectByMobilePhoneList(mobilePhoneList);
            Map<String, MbOrgEmployeeInfo> mobileEmpMap = Optional.ofNullable(mbOrgEmployeeInfos).orElse(Collections.emptyList())
                    .stream().collect(Collectors.toMap(item -> item.getMobilePhone(), Function.identity(), (k1, k2) -> k1));

            List<MbOrgInfo> mbOrgInfoList = organizationInfoService.listAll();

            /**
             * 参数传过来的部门orgId其实是businessCode，不是我们系统中的orgId
             */
            Map<String, MbOrgInfo> businessCodeMap = mbOrgInfoList.stream().collect(Collectors.toMap(item -> item.getBusinessCode(), Function.identity(), (k1, k2) -> k1));

            /**
             * 同步职级
             */
            positionInfoService.syncPosition4Employee(employeeList,businessCodeMap);

            //需要新增的集合
            List<SyncOrgEmployeeReq.Employee> addEmployeeList = new ArrayList<>();
            //需要修改的集合
            List<SyncOrgEmployeeReq.Employee> updateEmployeeList = new ArrayList<>();
            //需要删除的集合
            List<SyncOrgEmployeeReq.Employee> delEmployeeList = new ArrayList<>();
            //需要转移部门的集合
            List<SyncOrgEmployeeReq.Employee> transferOrgList = new ArrayList<>();

            // 获取岗位信息
            List<JobBo> jobBoList = jobService.listAllJobBo();
            Map<String, JobBo> jobNameMap = jobBoList.stream().collect(Collectors.toMap(JobBo::getName, item -> item, (k1, k2) -> k1));
            Map<String, JobBo> jobCodeMap = jobBoList.stream().collect(Collectors.toMap(JobBo::getCode, item -> item, (k1, k2) -> k1));
            log.info("所有岗位信息: jobBoList={}", jobBoList);

            List<SyncOrgEmployeeRsp.ErrorReason> errorReasonList = new ArrayList<>();
            for (SyncOrgEmployeeReq.Employee employee:request.getEmployeeList()){
                // 校验参数，并对orgId转换，参数传的是businessCode,转换为真正的orgId
                SyncOrgEmployeeRsp.ErrorReason errorReason = checkParams(employee, businessCodeMap, jobNameMap, jobCodeMap);
                if (Objects.nonNull(errorReason)){
                    errorReasonList.add(errorReason);
                    continue;
                }

                SyncOrgEmployeeReq.BasicInfo basicInfo = employee.getBasicInfo();

                MbUserOrgRelation userOrgRelation = uidOrgMap.get(basicInfo.getUid());
                if (Objects.nonNull(userOrgRelation)){
                    if(OpenApi_Action_Status_4.equals(basicInfo.getStatus())){
                        //删除
                        delEmployeeList.add(employee);
                    } else {
                        //修改
                        errorReason = updateCheckParams(employee, mobileEmpMap);
                        if (Objects.nonNull(errorReason)){
                            errorReasonList.add(errorReason);
                            continue;
                        }
                        updateEmployeeList.add(employee);
                        //变更身份/部门
                        if (StringUtils.isNotBlank(basicInfo.getOldOrgId()) ){
                            errorReason = transferEmployeeOrgParams(employee);
                            if (Objects.nonNull(errorReason)){
                                errorReasonList.add(errorReason);
                                continue;
                            }
                            transferOrgList.add(employee);
                        }
                    }
                } else {
                    //新增
                    errorReason = addCheckParams(employee, mobileEmpMap);
                    if (Objects.nonNull(errorReason)){
                        errorReasonList.add(errorReason);
                        continue;
                    }
                    addEmployeeList.add(employee);
                }

            }

            //调用MQ处理
            sendSyncEmployeeMQ(addEmployeeList, updateEmployeeList, delEmployeeList, transferOrgList);

            return SyncOrgEmployeeRsp.success(errorReasonList);
        }catch (Exception e){
            log.error("同步用户发生异常：", e);
            return SyncOrgEmployeeRsp.error();
        }
    }

    private void sendSyncEmployeeMQ(List<SyncOrgEmployeeReq.Employee> addEmployeeList, List<SyncOrgEmployeeReq.Employee> updateEmployeeList,
                                    List<SyncOrgEmployeeReq.Employee> delEmployeeList, List<SyncOrgEmployeeReq.Employee> transferOrgList){
        addEmployeeList.forEach(item ->{
            SyncEmployeeInfoMQBo employeeInfoMQBo = JsonUtils.convert(item, SyncEmployeeInfoMQBo.class);
            employeeInfoMQBo.setActionType("add");
            syncEmployeeInfoMQProducer.sendSyncEmployeeInfo(employeeInfoMQBo);
        });
        updateEmployeeList.forEach(item ->{
            SyncEmployeeInfoMQBo employeeInfoMQBo = JsonUtils.convert(item, SyncEmployeeInfoMQBo.class);
            employeeInfoMQBo.setActionType("update");
            syncEmployeeInfoMQProducer.sendSyncEmployeeInfo(employeeInfoMQBo);
        });
        delEmployeeList.forEach(item ->{
            SyncEmployeeInfoMQBo employeeInfoMQBo = JsonUtils.convert(item, SyncEmployeeInfoMQBo.class);
            employeeInfoMQBo.setActionType("delete");
            syncEmployeeInfoMQProducer.sendSyncEmployeeInfo(employeeInfoMQBo);
        });
        transferOrgList.forEach(item ->{
            SyncEmployeeInfoMQBo employeeInfoMQBo = JsonUtils.convert(item, SyncEmployeeInfoMQBo.class);
            employeeInfoMQBo.setActionType("transfer");
            syncEmployeeInfoMQProducer.sendSyncEmployeeInfo(employeeInfoMQBo);
        });
    }

    private SyncOrgEmployeeRsp.ErrorReason transferEmployeeOrgParams(SyncOrgEmployeeReq.Employee employee){
        SyncOrgEmployeeReq.BasicInfo basicInfo = employee.getBasicInfo();
        SyncOrgEmployeeRsp.ErrorReason errorReason = new SyncOrgEmployeeRsp.ErrorReason();
        errorReason.setOrgId(basicInfo.getOrgId());
        errorReason.setUid(basicInfo.getUid());
        MbUserOrgRelation mbUserOrgRelation = userOrgRelationService.find(basicInfo.getOldOrgId(), basicInfo.getUid());
        if (Objects.isNull(mbUserOrgRelation)){
            errorReason.setMessage("变更组织不存在该员工");
            return errorReason;
        }
        mbUserOrgRelation = userOrgRelationService.find(basicInfo.getOrgId(), basicInfo.getUid());
        if (Objects.nonNull(mbUserOrgRelation)){
            errorReason.setMessage("目的组织已经存在该员工");
            return errorReason;
        }
        return null;
    }

    private SyncOrgEmployeeRsp.ErrorReason updateCheckParams(SyncOrgEmployeeReq.Employee employee, Map<String, MbOrgEmployeeInfo> mobileEmpMap){
        SyncOrgEmployeeReq.BasicInfo basicInfo = employee.getBasicInfo();
        MbOrgEmployeeInfo mbOrgEmployeeInfo = mobileEmpMap.get(basicInfo.getMobilePhone());
        SyncOrgEmployeeRsp.ErrorReason errorReason = new SyncOrgEmployeeRsp.ErrorReason();
        errorReason.setOrgId(basicInfo.getOrgId());
        errorReason.setUid(basicInfo.getUid());
        if (Objects.nonNull(mbOrgEmployeeInfo) && !mbOrgEmployeeInfo.getUid().equalsIgnoreCase(basicInfo.getUid())){
            errorReason.setMessage("手机号码已经被其他员工使用");
            return errorReason;
        }
        return null;
    }

    private SyncOrgEmployeeRsp.ErrorReason addCheckParams(SyncOrgEmployeeReq.Employee employee, Map<String, MbOrgEmployeeInfo> mobileEmpMap){
        SyncOrgEmployeeReq.BasicInfo basicInfo = employee.getBasicInfo();
        MbOrgEmployeeInfo mbOrgEmployeeInfo = mobileEmpMap.get(basicInfo.getMobilePhone());
        SyncOrgEmployeeRsp.ErrorReason errorReason = new SyncOrgEmployeeRsp.ErrorReason();
        errorReason.setOrgId(basicInfo.getOrgId());
        errorReason.setUid(basicInfo.getUid());
        if (Objects.nonNull(mbOrgEmployeeInfo) && !mbOrgEmployeeInfo.getUid().equalsIgnoreCase(basicInfo.getUid())){
            errorReason.setMessage("手机号码已经被其他员工使用");
            return errorReason;
        }
        return null;
    }

    private SyncOrgEmployeeRsp.ErrorReason checkParams(SyncOrgEmployeeReq.Employee employee, Map<String, MbOrgInfo> orgMap, Map<String, JobBo> jobNameMap, Map<String, JobBo> jobCodeMap){
        SyncOrgEmployeeRsp.ErrorReason errorReason = new SyncOrgEmployeeRsp.ErrorReason();
        SyncOrgEmployeeReq.BasicInfo basicInfo = employee.getBasicInfo();
        if (Objects.isNull(basicInfo)){
            errorReason.setMessage("basicInfo不能为空");
            return errorReason;
        }

        errorReason.setOrgId(StringUtils.isBlank(basicInfo.getOrgId()) ? "" : basicInfo.getOrgId());
        errorReason.setUid(StringUtils.isBlank(basicInfo.getUid()) ? "" : basicInfo.getUid());
        if (StringUtils.isBlank(basicInfo.getUid())){
            errorReason.setMessage("员工编码不能为空");
            return errorReason;
        }
        if (StringUtils.isBlank(basicInfo.getOrgId())){
            errorReason.setMessage("组织编码不能为空");
            return errorReason;
        }
        if (StringUtils.isBlank(basicInfo.getName())){
            errorReason.setMessage("员工名称不能为空");
            return errorReason;
        }
        if (StringUtils.isBlank(basicInfo.getMobilePhone())){
            errorReason.setMessage("手机号码不能为空");
            return errorReason;
        }

        if (!RegularUtils.isMobile(basicInfo.getMobilePhone())){
            errorReason.setMessage("手机号码不正确");
            return errorReason;
        }

        Integer employeeType = basicInfo.getEmployeeType();
        if(Objects.isNull(employeeType) || (employeeType != 0 && employeeType != 1)){
            basicInfo.setEmployeeType(0);
        }

        if (StringUtils.isBlank(basicInfo.getCountryCode())){
            basicInfo.setCountryCode("+86");
        }
        if (StringUtils.isNotBlank(basicInfo.getCountryCode()) && basicInfo.getCountryCode().indexOf("+") < 0){
            basicInfo.setCountryCode("+" + basicInfo.getCountryCode());
        }

        if (StringUtils.isNotBlank(basicInfo.getEmail()) && !RegularUtils.isEmail(basicInfo.getEmail())){
            errorReason.setMessage("邮箱格式不正确");
            return errorReason;
        }

        if (StringUtils.isNotBlank(basicInfo.getGender()) && !"M".equalsIgnoreCase(basicInfo.getGender()) && !"F".equalsIgnoreCase(basicInfo.getGender())){
            errorReason.setMessage("性别格式不正确,需填写（M,F）");
            return errorReason;
        }

        MbOrgInfo mbOrgInfo = orgMap.get(basicInfo.getOrgId());
        if (Objects.isNull(mbOrgInfo)){
            errorReason.setMessage("系统中不存在该组织编码");
            return errorReason;
        }
        // orgId转换
        basicInfo.setOrgId(mbOrgInfo.getOrgId());

        if (StringUtils.isNotBlank(basicInfo.getOldOrgId())){
            mbOrgInfo = orgMap.get(basicInfo.getOldOrgId());
            if (Objects.isNull(mbOrgInfo)){
                errorReason.setMessage("员工变更组织编码在系统中不存在");
                return errorReason;
            }
            // oldOrgId转换
            basicInfo.setOldOrgId(mbOrgInfo.getOrgId());
        }

        if (StringUtils.isBlank(basicInfo.getStatus())){
            errorReason.setMessage("状态不能为空");
            return errorReason;
        }

        List<SyncOrgEmployeeReq.CardType> cardTypeList = employee.getCardTypeList();
        if (CollectionUtils.isNotEmpty(cardTypeList)){
            for (SyncOrgEmployeeReq.CardType cardType:cardTypeList){
                if (StringUtils.isBlank(cardType.getCardType())){
                    errorReason.setMessage("证件类型不能为空");
                    return errorReason;
                }

                if (!RegularUtils.isNumer(cardType.getCardType())){
                    errorReason.setMessage("证件类型需填写数字类型");
                    return errorReason;
                }

                if (StringUtils.isBlank(CardTypeSwitchUtil.getNameById(Integer.parseInt(cardType.getCardType())))){
                    errorReason.setMessage("证件类型枚举匹配失败");
                    return errorReason;
                }

                if (StringUtils.isBlank(cardType.getCardNo())){
                    errorReason.setMessage("证件号不能为空");
                    return errorReason;
                }

                if (StringUtils.isNotBlank(cardType.getTimeLimit())){
                    try {
                        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
                        simpleDateFormat.parse(cardType.getTimeLimit());
                    }catch (Exception e){
                        errorReason.setMessage("请填写正确的日期格式为：yyyy-MM-dd");
                        return errorReason;
                    }
                }

                if (CardCodeEnum.ID_CARD.getCode().equals(cardType.getCardType())){
                    if (!IdcardUtil.isValidCard(cardType.getCardNo())){
                        errorReason.setMessage("身份证格式不正确");
                        return errorReason;
                    }
                }

            }
        }
        // 岗位校验
        CheckJobResultBo checkJobResultBo = jobService.checkJobNameAndJobCode(basicInfo.getJobName(), basicInfo.getJobCode(), mbOrgInfo.getOrgId(), basicInfo.getUid(), jobNameMap, jobCodeMap);
        if (checkJobResultBo != null) {
            if (StringUtils.isNotBlank(checkJobResultBo.getErrorMsg())) {
                errorReason.setMessage(checkJobResultBo.getErrorMsg());
                return errorReason;
            }
            basicInfo.setJobId(checkJobResultBo.getJobId());
            employee.setBasicInfo(basicInfo);
        }
        return null;
    }


    private String getOrgUidKey(String orgId, String uid){
        return String.format("%s_%s", orgId, uid);
    }
}
